#!/usr/bin/python

import string
import time
import datetime
import smtplib
import copy

import ForecastCollective
import BeachData

class EmailReport:
	"A simple object that builds up an email based report"
	def __init__(self):
		self.reportStr = ''
		self.smtpServer = 'smtp.gmail.com'
		self.addressFrom = 'surfScraper@email.com'
		self.subject = 'Beach surf data as of %s\n' % datetime.date.today()
		self.gmailUser = '<<USERNAME>>'
		self.gmailPass = '<<PASS>>'
	
	################################
	# Slowly build up the report	
	def addToReport(self, stringToAdd):
		self.reportStr += (stringToAdd + "\n")
	
	################################
	# Send email message of report	
	def sendEmailReport(self, addressTo):
		smtpSvr = smtplib.SMTP(self.smtpServer,587)
		smtpSvr.ehlo()
		smtpSvr.starttls()
		smtpSvr.ehlo
		smtpSvr.login(self.gmailUser, self.gmailPass)
		msgHeader = 'To:' + addressTo + '\n' + 'From: ' + self.gmailUser + '\n' + 'Subject:' + self.subject + '\n'
		msg = msgHeader + '\n' + self.reportStr
		smtpSvr.sendmail(self.gmailUser, addressTo, msg)
		smtpSvr.close()
		return 0
	
class SmsReport:
	"A simple object that builds up an sms based report"
	def __init__(self):
		self.reportStr = 'Beach Data @ %s\n' %datetime.date.today()
		self.destNumber = '+000000000'		
	
	################################
	# Slowly build up the report	
	def addToReport(self, stringToAdd):
		self.reportStr += (self.reportStr + stringToAdd + "\n")
		return 0
	
	###########################
	# Send report via Skype SMS
	def sendSkypeSmsReport(self):
		skypeObj = Skype4Py.Skype()
		skypeObj.Attach()
		sms = skypeObj.CreateSms(Skype4Py.smsMessageTypeOutgoing, self.destNumber)
		sms.Body = self.reportStr
		sms.Send()
		return 0


##########################################
# A Complicated function that compares collectives and allows for all possible situations regarding the
# difference in forecasts. Although this is a big chunk of logic, it seems the most readable given the circumstances
# Fixme: Improve, seperate, and reduce this function
def compareCollectives(oldBeachObjCollective, newBeachObjCollective):
	emailReport = Reports.EmailReport()
	smsReport = Reports.SmsReport()
	BOC_new_copy = copy.deepcopy(newBeachObjCollective)

	for newBeachObj in BOC_new_copy.beachObjList:
		oldDataFound = False
		for oldBeachObj in oldBeachObjCollective.beachObjList:
			if (oldBeachObj.beachNumber == newBeachObj.beachNumber):
				oldDataFound = True
				oldTime = datetime.datetime(*time.strptime(str(oldBeachObj.asOf), "%Y-%m-%d")[0:5])
				newTime = datetime.datetime(*time.strptime(str(newBeachObj.asOf), '%Y-%m-%d')[0:5])
				timeDelta = (newTime - oldTime)

				if (timeDelta.days == 0):
					print 'Old data and new data are *same* data - will send the forecast as-is.'
					emailReport.addToReport(str(oldBeachObj))

				elif (timeDelta.days < 7):																# Check the data is actually for the same week
					for (ratingPos, newRating) in enumerate(newBeachObj.starRatings):
						if (ratingPos + timeDelta.days) >= len(oldBeachObj.starRatings):
							emailReport.addToReport('No previous data for beach %s re. day: %s, new data: %s' % \
													(newBeachObj.beachName, newBeachObj.dataDays[ratingPos], newRating))

						else:
							oldRating = oldBeachObj.starRatings[ratingPos + timeDelta.days]
							oldRatingCount = oldRating.count('*')
							newRatingCount = newRating.count('*')
							oldDataDay = oldBeachObj.dataDays[ratingPos + timeDelta.days]
							oldBeachName = oldBeachObj.beachName

							if (newRatingCount == oldRatingCount):
								if (newRatingCount >= starMinLimit):
									emailReport.addToReport('Rating for %s is same (surfable) re: %s (%s)' % (oldBeachName, oldDataDay, newRating))
								else:
									emailReport.addToReport('Rating for %s is same (unsurfable) re: %s (%s)' % (oldBeachName, oldDataDay, newRating))

							elif (newRatingCount > oldRatingCount):
								if (newRatingCount < starMinLimit):
									emailReport.addToReport('Rating for %s has improved, but is still unsurfable re: %s (%s:%s)' % \
															(oldBeachName, oldDataDay, oldRating, newRating))

								elif (oldRatingCount >= starMinLimit):
									emailReport.addToReport('Rating for %s has improved, and is even more surfable re: %s (%s:%s)' % \
															(oldBeachName, oldDataDay, oldRating, newRating))
								else:
									emailReport.addToReport('Rating for %s is now at surf threshold re: %s (%s:%s)' % \
															(oldBeachName, oldDataDay, oldRating, newRating))
									smsReport.addToReport('Rating for %s is now at surf threshold re: %s (%s:%s)' % \
												(oldBeachName, oldDataDay, oldRating, newRating))

							elif (newRatingCount < oldRatingCount):
								if (newRatingCount >= starMinLimit):
									emailReport.addToReport('Rating for %s is worse then before, but still surfable re: %s (%s:%s)' % \
															(oldBeachName, oldDataDay, oldRating, newRating))

								elif (oldRatingCount < starMinLimit):
									emailReport.addToReport('Rating for %s is now even less surfable re: %s (%s:%s)' % \
															(oldBeachName, oldDataDay, oldRating, newRating))

								else:
									emailReport.addToReport('Rating for %s is no longer surfable re: %s (%s:%s)' % \
															(oldBeachName, oldDataDay, oldRating, newRating))
									smsReport.addToReport('Rating for %s no longer surfable re: %s (%s:%s)' % \
															(oldBeachName, oldDataDay, oldRating, newRating))

							else:
								print 'Error in compareCollectives() data comparison, no discreet outcome determined for %s re: %s' % \
									  (oldBeachName, oldDataData)
				else:
					print 'New data is for diffrent timespan than old - reporting all!'
					for newBeachObj in newBeachObjCollective.beachObjList:
						emailReport.addToReport(str(newBeachObj))

		if (oldDataFound == False):
			emailReport.addToReport('Beach %s not in old data: forecast is %s %s, respectively' % (newBeachObj.beachName, newBeachObj.dataDays, newBeachObj.starRatings))
			smsReport.addToReport('Beach %s not found in old; no report made' % (newBeachObj.beachName))

	return (emailReport, smsReport)
